#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/sha.h>
#include <openssl/rand.h>

// 定义会员卡结构体
struct Membership {
    char nickname[100]; // 昵称
    char phoneNumber[12]; // 手机号
    double balance; // 余额
    unsigned char passwordHash[SHA256_DIGEST_LENGTH]; // 密码哈希
};

#define MAX_BOOKS 100

// 定义图书结构体
struct Book {
    char title[100];  // 图书标题
    char author[100]; // 图书作者
    int year;         // 出版年份
    int available;    // 是否可借，1表示可借，0表示已借出
    time_t dueDate;   // 归还日期的时间戳
};

// 定义图书馆结构体
struct Library {
    struct Book books[MAX_BOOKS];  // 图书数组
    int numBooksDeleted;           // 已删除的图书数量
    int numBooks;                  // 当前图书馆中的图书数量
};

// 保存会员卡信息到文件
void saveMembershipsToFile(const struct Membership* memberships, int numMemberships) {
    FILE* file = fopen("memberships.txt", "w");
    if (file == NULL) {
        printf("无法保存会员卡信息\n");
        return;
    }

    for (int i = 0; i < numMemberships; i++) {
        const struct Membership* membership = &memberships[i];
        fprintf(file, "%s\t%s\t%.2lf\t", membership->nickname, membership->phoneNumber, membership->balance);

        // 保存密码哈希
        for (int j = 0; j < SHA256_DIGEST_LENGTH; j++) {
            fprintf(file, "%02x", membership->passwordHash[j]);
        }
        fprintf(file, "\n");
    }

    fclose(file);
}

// 从文件加载会员卡信息
void loadMembershipsFromFile(struct Membership* memberships, int* numMemberships) {
    FILE* file = fopen("memberships.txt", "r");
    if (file == NULL) {
        printf("无法加载会员卡信息\n");
        return;
    }

    while (*numMemberships < MAX_BOOKS) {
        struct Membership* membership = &memberships[*numMemberships];
        if (fscanf(file, "%s\t%s\t%lf\t", membership->nickname, membership->phoneNumber, &membership->balance) == 3) {
            // 读取密码哈希
            char hexHash[2 * SHA256_DIGEST_LENGTH + 1];
            if (fscanf(file, "%64s\n", hexHash) == 1) {
                for (int j = 0; j < SHA256_DIGEST_LENGTH; j++) {
                    sscanf(hexHash + 2 * j, "%2hhx", &membership->passwordHash[j]);
                }
                (*numMemberships)++;
            }
            else {
                // 读取密码哈希失败，可能是无效数据，跳过该行
                fscanf(file, "%*[^\n]\n");
            }
        }
        else {
            // 读取数据不成功，可能是文件末尾或无效数据，退出循环
            break;
        }
    }

    fclose(file);
}

// 登录会员卡
int loginMembership(struct Membership* memberships, int numMemberships) {
    char phoneNumber[12];
    char password[20];
    printf("请输入手机号: ");
    scanf("%s", phoneNumber);
    printf("请输入密码: ");
    scanf("%s", password);

    unsigned char inputPasswordHash[SHA256_DIGEST_LENGTH];
    SHA256((unsigned char*)password, strlen(password), inputPasswordHash);

    for (int i = 0; i < numMemberships; i++) {
        if (strcmp(memberships[i].phoneNumber, phoneNumber) == 0) {
            printf("Loaded Password Hash: ");
            for (int j = 0; j < SHA256_DIGEST_LENGTH; j++) {
                printf("%02x", memberships[i].passwordHash[j]);
            }
            printf("\n");

            printf("Input Password Hash: ");
            for (int j = 0; j < SHA256_DIGEST_LENGTH; j++) {
                printf("%02x", inputPasswordHash[j]);
            }
            printf("\n");

            if (memcmp(memberships[i].passwordHash, inputPasswordHash, SHA256_DIGEST_LENGTH) == 0) {
                printf("登录成功，欢迎回来，%s！\n", memberships[i].nickname);
                return i; // 返回会员卡索引
            }
        }
    }

    printf("登录失败，手机号或密码错误。\n");
    return -1; // 登录失败
}

// 验证手机号是否符合中国手机号规范（简化版）
int validatePhoneNumber(const char* phoneNumber) {
    // 在实际应用中，应使用正则表达式或更详细的规则来验证手机号
    // 此处仅作示例
    return strlen(phoneNumber) == 11;
}

// 验证密码是否符合要求（至少10位且不含特殊符号，简化版）
int validatePassword(const char* password) {
    // 在实际应用中，应使用更复杂的规则来验证密码
    // 此处仅作示例
    return strlen(password) >= 10 && strcspn(password, "!@#$%^&*()_+[]{}|\\:;<>,.?/~") == strlen(password);
}

// 注册会员卡
void registerMembership(struct Membership* memberships, int* numMemberships) {
    if (*numMemberships >= MAX_BOOKS) {
        printf("会员卡数量已达上限，无法注册新会员卡。\n");
        return;
    }

    struct Membership* membership = &memberships[*numMemberships];

    // 输入会员信息
    printf("请输入昵称: ");
    scanf("%s", membership->nickname);

    // 输入手机号，并验证是否符合中国手机号规范
    while (1) {
        printf("请输入手机号: ");
        scanf("%s", membership->phoneNumber);
        int exists = 0;
        for (int i = 0; i < *numMemberships; i++) {
            if (strcmp(memberships[i].phoneNumber, membership->phoneNumber) == 0) {
                exists = 1;
                break;
            }
        }
        if (exists) {
            printf("该手机号已存在，请重新输入。\n");
        }
        else if (validatePhoneNumber(membership->phoneNumber)) {
            break;
        }
        else {
            printf("请输入正确的手机号。\n");
        }
    }

    // 输入密码，并验证长度和特殊符号
    while (1) {
        char password[20];
        char confirmPassword[20];
        printf("请输入密码 (至少10位且不含特殊符号): ");
        scanf("%s", password);
        printf("请确认密码: ");
        scanf("%s", confirmPassword);
        if (validatePassword(password) && strcmp(password, confirmPassword) == 0) {
            SHA256((unsigned char*)password, strlen(password), membership->passwordHash);
            break;
        }
        else {
            printf("密码不符合要求或两次输入不匹配，请重新输入。\n");
        }
    }

    membership->balance = 100.0; // 初始余额为100元
    (*numMemberships)++;
    printf("注册成功，欢迎加入，%s！\n", membership->nickname);
}

// 查询会员卡信息
void queryMembership(const struct Membership* membership) {
    printf("会员昵称: %s\n", membership->nickname);
    printf("手机号: %s\n", membership->phoneNumber);
    printf("余额: %.2lf元\n", membership->balance);
}



// 初始化图书馆
void initLibrary(struct Library* library) {
    library->numBooks = 0;
}

// 添加图书
void addBook(struct Library* library) {
    if (library->numBooks >= MAX_BOOKS) {
        printf("图书馆已满，无法添加更多图书。\n");
        return;
    }

    struct Book* book = &library->books[library->numBooks];
    printf("请输入图书标题: ");
    scanf("%s", book->title);
    printf("请输入图书作者: ");
    scanf("%s", book->author);
    printf("请输入出版年份: ");
    scanf("%d", &book->year);
    book->available = 1; // 初始状态为可借
    book->dueDate = 0;   // 归还日期初始化为0
    (library->numBooks)++;
    printf("图书已添加\n");
}

// 查看图书
void viewBooks(const struct Library* library) {
    if (library->numBooks == 0) {
        printf("图书馆为空\n");
        return;
    }

    printf("图书列表:\n");
    for (int i = 0; i < library->numBooks; i++) {
        const struct Book* book = &library->books[i];
        printf("图书%d:\n", i + 1);
        printf("标题: %s\n", book->title);
        printf("作者: %s\n", book->author);
        printf("年份: %d\n", book->year);
        printf("状态: %s\n", book->available ? "可借" : "已借出");
        if (!book->available) {
            printf("归还日期: %s\n", ctime(&book->dueDate));
        }
        printf("\n");
    }
}

// 搜索图书
void searchBooks(const struct Library* library) {
    if (library->numBooks == 0) {
        printf("图书馆为空\n");
        return;
    }

    char keyword[100];
    printf("请输入搜索关键字 (标题或作者): ");
    scanf("%s", keyword);

    printf("搜索结果:\n");
    for (int i = 0; i < library->numBooks; i++) {
        const struct Book* book = &library->books[i];
        if (strstr(book->title, keyword) || strstr(book->author, keyword)) {
            printf("图书%d:\n", i + 1);
            printf("标题: %s\n", book->title);
            printf("作者: %s\n", book->author);
            printf("年份: %d\n", book->year);
            printf("状态: %s\n", book->available ? "可借" : "已借出");
            if (!book->available) {
                printf("归还日期: %s\n", ctime(&book->dueDate));
            }
            printf("\n");
        }
    }
}

// 借书
void borrowBook(struct Library* library) {
    if (library->numBooks == 0) {
        printf("图书馆为空\n");
        return;
    }

    int index;
    printf("请输入要借阅的图书索引 (1-%d): ", library->numBooks);
    scanf("%d", &index);

    if (index < 1 || index > library->numBooks) {
        printf("无效的索引\n");
        return;
    }

    struct Book* book = &library->books[index - 1];
    if (!book->available) {
        printf("该图书已借出，请选择其他图书。\n");
    }
    else {
        book->available = 0;
        time_t now;
        time(&now);
        book->dueDate = now + 60; // 归还日期为借阅后的一分钟后
        printf("借阅成功，归还日期: %s\n", ctime(&book->dueDate));
    }
}

// 还书
void returnBook(struct Library* library) {
    if (library->numBooks == 0) {
        printf("图书馆为空\n");
        return;
    }

    int index;
    printf("请输入要归还的图书索引 (1-%d): ", library->numBooks);
    scanf("%d", &index);

    if (index < 1 || index > library->numBooks) {
        printf("无效的索引\n");
        return;
    }

    struct Book* book = &library->books[index - 1];
    if (book->available) {
        printf("该图书没有借出记录，无法归还。\n");
    }
    else {
        time_t now;
        time(&now);
        if (now > book->dueDate) {
            // 超过归还日期，需要缴纳滞纳金
            int minutesLate = (int)(now - book->dueDate) / 60; // 计算超过的分钟数
            int lateFee = minutesLate > 1 ? minutesLate * 100 : 100; // 如果超过1分钟，按每分钟100元计费
            printf("图书已超过归还日期 %d 分钟，需要缴纳滞纳金 %d 元。\n", minutesLate, lateFee);
        }
        else {
            printf("归还成功\n");
        }
        book->available = 1;
        book->dueDate = 0;
    }
}

// 删除图书
void deleteBook(struct Library* library, int index) {
    if (index < 1 || index > library->numBooks) {
        printf("无效的索引\n");
        return;
    }

    // 将图书数组中的图书向前移动，覆盖被删除的图书
    for (int i = index - 1; i < library->numBooks - 1; i++) {
        memcpy(&library->books[i], &library->books[i + 1], sizeof(struct Book));
    }

    // 清空最后一个图书的数据
    memset(&library->books[library->numBooks - 1], 0, sizeof(struct Book));

    // 更新图书数量和已删除的图书数量
    (library->numBooks)--;
    (library->numBooksDeleted)++;
}

// 保存图书信息到文件
void saveLibraryToFile(const struct Library* library) {
    FILE* file = fopen("library.txt", "w");
    if (file == NULL) {
        printf("无法保存图书信息\n");
        return;
    }

    for (int i = 0; i < library->numBooks; i++) {
        const struct Book* book = &library->books[i];
        fprintf(file, "%s\t%s\t%d\t%d\t%lld\n", book->title, book->author, book->year, book->available, book->dueDate);
    }

    fclose(file);
}

// 从文件加载图书信息
void loadLibraryFromFile(struct Library* library) {
    FILE* file = fopen("library.txt", "r");
    if (file == NULL) {
        printf("无法加载图书信息\n");
        return;
    }

    while (library->numBooks < MAX_BOOKS) {
        struct Book* book = &library->books[library->numBooks];
        if (fscanf(file, "%s\t%s\t%d\t%d\t%lld", book->title, book->author, &book->year, &book->available, &book->dueDate) == 5) {
            (library->numBooks)++;
        }
        else {
            // 读取数据不成功，可能是文件末尾或无效数据，退出循环
            break;
        }
    }

    fclose(file);
}

// 充值会员卡余额
void rechargeMembership(struct Membership* membership) {
    double amount;
    printf("请输入充值金额: ");
    scanf("%lf", &amount);

    if (amount <= 0) {
        printf("充值金额必须大于0。\n");
    }
    else {
        membership->balance += amount;
        printf("充值成功，当前余额: %.2lf元\n", membership->balance);
    }
}

// 在初始化图书馆之前清空图书数据
void clearLibrary(struct Library* library) {
    library->numBooks = 0;
    library->numBooksDeleted = 0;
    memset(library->books, 0, sizeof(library->books));
}

int main() {
    struct Library library;
    struct Membership memberships[MAX_BOOKS];
    int numMemberships = 0; // 记录会员卡数量

    initLibrary(&library);
    clearLibrary(&library); // 清空图书库数据
    loadLibraryFromFile(&library); // 从文件加载图书信息
    loadMembershipsFromFile(memberships, &numMemberships); // 从文件加载会员卡信息

    int choice;
    int loggedInMembershipIndex = -1; // 当前登录的会员卡索引

    while (1) {
        printf("\n图书管理程序\n");
        if (loggedInMembershipIndex == -1) {
            printf("1. 会员登录\n");
            printf("2. 会员注册\n");
        }
        else {
            printf("3. 添加图书\n");
            printf("4. 查看图书\n");
            printf("5. 搜索图书\n");
            printf("6. 借阅图书\n");
            printf("7. 归还图书\n");
            printf("8. 删除图书\n");
            printf("9. 充值\n");
            printf("10. 查询会员卡信息\n");
            printf("11. 保存并退出\n");
        }
        printf("请选择操作: ");
        scanf("%d", &choice);

        if (loggedInMembershipIndex == -1) {
            // 如果未登录，只处理登录和注册操作
            switch (choice) {
            case 1:
                loggedInMembershipIndex = loginMembership(memberships, numMemberships);
                break;
            case 2:
                registerMembership(memberships, &numMemberships);
                saveMembershipsToFile(memberships, numMemberships); // 注册成功后保存会员卡信息
                break;
            default:
                printf("无效的选项\n");
            }
        }
        else {
            // 如果已登录，处理其他图书管理操作
            switch (choice) {
            case 3:
                addBook(&library);
                break;
            case 4:
                viewBooks(&library);
                break;
            case 5:
                searchBooks(&library);
                break;
            case 6:
                borrowBook(&library);
                break;
            case 7:
                returnBook(&library);
                break;
            case 8:
                if (library.numBooksDeleted >= library.numBooks) {
                    printf("所有图书都已删除\n");
                }
                else {
                    int deleteIndex;
                    printf("请输入要删除的图书索引 (1-%d): ", library.numBooks);
                    scanf("%d", &deleteIndex);
                    deleteBook(&library, deleteIndex);
                    printf("图书已删除\n");
                }
                break;
            case 9:
                rechargeMembership(&memberships[loggedInMembershipIndex]);
                saveMembershipsToFile(memberships, numMemberships); // 充值成功后保存会员卡信息
                break;
            case 10:
                queryMembership(&memberships[loggedInMembershipIndex]);
                break;
            case 11:
                saveLibraryToFile(&library); // 保存图书信息到文件
                saveMembershipsToFile(memberships, numMemberships); // 退出前保存会员卡信息
                exit(0);
            default:
                printf("无效的选项\n");
            }
        }
    }

    return 0;
}